using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using UniVRM10;
public class VBodyLanguageDescAssembly : MonoBehaviour
{
    public static Dictionary<string, float> speechSpeedMap = new()
    {
        ["down"] = 4,
        ["nil"] = 5,
        ["scare"] = 6,
        ["anger"] = 10,
    };

    public class Slice
    {
        public string text;
        public float motionBeyongVoice = 0;
        public string motion; // 为null则说明保持上一个动作
        public string tone; // 对照语气可以查出语速, 语气也与
        public bool eyeMotion = false; // 应该是一个枚举 
    }



    [Button]
    public void StartT()
    {
        var sample = new Slice()
        {
            tone = "scare",
            text = "我从来没见过",
            motion = "nil",
            motionBeyongVoice = 0,
            eyeMotion = false
        };

        var ex = new VRM10Expression();
        var a = GetComponent<Vrm10Instance>();
        var exp = a.Runtime.Expression;
        var vrm = a.Vrm;

        exp.SetWeight(ExpressionKey.Angry, 1);
    }

    //Slice 是一个缓冲区中的最小执行队列, 由声音播放的回调决定是否完成

    //作为剧本单元, slice还处理交互事件回调等待 , 有一个主要驱动单元, 着重表现什么, 台词? 动作? 事件? 
    public class DramaBlock
    {
        /// <summary>
        /// 根据主要驱动块的类型来决定谁来等待
        /// </summary>
        public string MainDrive = "Speech / Action / Event";
        public string speech = ""; //三类统一的驱动名
        public string action = "";
        public string dramaEvent = "";
        public string dramaEventParma = "";

        public bool waitSpeech = true;
        public DramaBlock CreateSample()
        {
            var sample1 = new DramaBlock()
            {
                speech = "我真想给你一耳光",
                action = "举手假装打",
                dramaEvent = "nil",
            };
            //思考slice和motion的关系
            var sample2 = new DramaBlock()
            {
                speech = "汽水吗,我给你拿",
                action = "nil",
                dramaEvent = "Fetch",
                dramaEventParma = "cola",
            };
 

            return sample1;
        }
    }
    //实际上Fetch cola这个事件就已经足够完全重构现有机制了,
    //比如Fetch 需要对cola展开联想 , 关联地点, cola -> 冰箱, 桌子 , 是相对序列化的信息
    //Fetch_Wrap_GoToPlace(Fridge).Next( Fetch_Wrap_CheckExist(cola)).Catch(new stringInfo(Desk,Fridge,RestRoom))
    // .ParallSelect(true,Fetch_Wrap_Gain(cola).Next(Fetch_Wrap_GoBack().Next(Fetch_Wrap_Give())))
    // .ParallSelect(false,Fetch_Wrap_GoToPlace(Catch.Another))
    //      .NextLayer()
    //      .Success().
    //      .Fail().


    //一个行为遵从主体逻辑, 会有一些变体, 这部分工作可以交给社区,比如性格后缀的配置, 
    //不一定需要完全走本地配置, 走服务器读取行为预设 , 这样可以做到社区的更新和审查

    //所有的等待都是根据轮询标志位来的


    //所以 一个DramaEvent最终需要展开为一颗行为树, 节点执行中的状态和Block的关系也需要梳理
    public class MotionTree
    {
        public List<MotionNodeGroup> layer;
        public int curLayer = 0;
        public void Sample()
        {
            var tree = new MotionTree().Next("GoToPlace");
        }
        public MotionTree Next(Motion Node)
        {
            return this;
        }

        public MotionTree Next(string nodeActName)
        {
            layer[curLayer++] = new MotionNodeGroup(nodeActName);
            return this;
        }

        public object Param;
        public MotionTree Catch(object obj)
        {
            Param = obj;
            return this;
        }

        public void Consume(VActBehaviour actBehaviour)
        {
            int runtimeLayer = 0;
            layer[runtimeLayer].node.ToString();

            while (runtimeLayer < layer.Count)
            {
                var action = actBehaviour.actions[layer[runtimeLayer].node.actionName];
                action.Subscribe(); // 这一步需要传入参数 , 或者需要拿到执行结果
            }
        }
    }

    public class MotionNodeGroup
    {
        public MotionNode node;
        public List<MotionNode> nodes;

        public MotionNodeGroup(string actNodeName)
        {
            node = new MotionNode() { actionName = actNodeName };
        }

    }

    public class MotionNode
    {
        public string actionName;
    }
}
